#ifndef _ZW_DP_TYPES_H
#define _ZW_DP_TYPES_H

#include <stdint.h>
#include <inttypes.h>
#include <x86intrin.h>


#ifdef __cplusplus
extern "C" {
#endif

#ifndef CONFIG_IP_STATE_CUCKOO_HASH
#if defined(__RDSEED__) && defined(__ADX__)
//#define CONFIG_IP_STATE_CUCKOO_HASH
#endif
#endif

/*****************************************************************************/

#ifndef MAX_PATH
#define MAX_PATH 256
#endif


#ifndef UCHAR_MAX
#define UCHAR_MAX	((u8)(~0U))
#endif

#ifndef USHORT_MAX
#define USHORT_MAX	((u16)(~0U))
#endif

#ifndef UINT_MAX
#define UINT_MAX    ((u32)(~0U))
#endif

#ifndef TRUE
#define TRUE 1
#endif

#ifndef true
#define true 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

#ifndef false
#define false 0
#endif

#ifndef MB
#define MB	(1024*1024UL)
#endif

#ifndef GB
#define GB  (1024UL * MB)
#endif

/*****************************************************************************/

#define __cold			__attribute__((cold))
#define __hot			__attribute__((hot))

//#define INLINE __attribute__((always_inline,unused))
#ifndef __always_inline
#define __always_inline		inline __attribute__((always_inline))
#endif

#ifndef __zw_dp_unused
#define __zw_dp_unused			__attribute__((unused))
#endif

#ifndef __noreturn
#define __noreturn __attribute__((noreturn)) 
#endif

#ifndef __no_optimize
#define __no_optimize __attribute__((optimize("-O0")))
#endif

/*
 * From the GCC manual:
 *
 * Many functions have no effects except the return value and their
 * return value depends only on the parameters and/or global
 * variables.  Such a function can be subject to common subexpression
 * elimination and loop optimization just as an arithmetic operator
 * would be.
 * [...]
 */
#ifndef __pure
#define __pure				__attribute__((pure))
#endif

#ifndef __aligned
#define __aligned(x)			__attribute__((aligned(x)))
#endif

#ifndef __printf
#define __printf(a,b)			__attribute__((format(printf,a,b)))
#endif

#ifndef __packed
#define __packed 			__attribute__((packed))
#endif

#ifndef __noinline
#define  __noinline			__attribute__((noinline))
#endif

#ifndef __attribute_const__
#define __attribute_const__		__attribute__((__const__))
#endif

#ifndef __maybe_unused
#define __maybe_unused			__attribute__((unused))
#endif
#ifndef __always_unused
#define __always_unused			__attribute__((unused))
#endif

#define INLINE inline
#define UNUSED(x) (void)x  

#define L2_CACHELINE_SIZE (64)
#define L1_CACHELINE_SIZE (64)

#define _SHARED_SECTION   __attribute__((section(".shared")))
#define _TCP_ACK_SECTION  __attribute__((section(".ack")))
#define __attr_hot_section  __attribute__((hot,section(".hot")))
#define __attr_cold_section  __attribute__((cold,section(".cold")))

#define HW_L2_ALIGNED __attribute__((aligned(L2_CACHELINE_SIZE)))
#define HW_L1_ALIGNED __attribute__((aligned(L1_CACHELINE_SIZE)))

/*****************************************************************************/
#include <stdint.h>
typedef signed char s8;
typedef unsigned char u8;

typedef signed short s16;
typedef unsigned short u16;

typedef signed int s32;
typedef unsigned int u32;

typedef int64_t s64;
typedef uint64_t u64;

//typedef uint8_t bool;

typedef s16 	INT16;
typedef u16 	UINT16;
typedef s32		INT32;
typedef u32 	UINT32;
typedef s8 		CHAR8;
typedef u8 		UCHAR8;

typedef unsigned char UCHAR;
typedef unsigned char * PUCHAR;
typedef unsigned long DWORD;
typedef unsigned long * PDWORD;
typedef unsigned short WORD;
typedef unsigned int UINT;
typedef int INT;
typedef long BOOL;
typedef unsigned char BYTE;
typedef unsigned long ULONG;
typedef unsigned long ULONG_PTR; 

typedef ULONG_PTR DWORD_PTR ;


/*****************************************************************************/
#ifndef __KERNEL__
/*
 *      Display an IP address in readable format.
 */

#define NIPTHREE(addr) \
	((unsigned char *)&addr)[0], \
	((unsigned char *)&addr)[1], \
	((unsigned char *)&addr)[2]

#define NIPQUAD(addr) \
	((unsigned char *)&addr)[0], \
	((unsigned char *)&addr)[1], \
	((unsigned char *)&addr)[2], \
	((unsigned char *)&addr)[3]

#define HIPQUAD(addr) \
	((unsigned char *)&addr)[3], \
	((unsigned char *)&addr)[2], \
	((unsigned char *)&addr)[1], \
	((unsigned char *)&addr)[0]
	
#define NIPQUAD_FMT "%u.%u.%u.%u"

#define NIPQUAD_PTR(addr) \
	((unsigned char *)addr)[0], \
	((unsigned char *)addr)[1], \
	((unsigned char *)addr)[2], \
	((unsigned char *)addr)[3]
	
#define NIP6(addr) \
	ntohs((addr).s6_addr16[0]), \
	ntohs((addr).s6_addr16[1]), \
	ntohs((addr).s6_addr16[2]), \
	ntohs((addr).s6_addr16[3]), \
	ntohs((addr).s6_addr16[4]), \
	ntohs((addr).s6_addr16[5]), \
	ntohs((addr).s6_addr16[6]), \
	ntohs((addr).s6_addr16[7])

#define NIP6_PTR(addr) \
	ntohs(((uint16_t *)addr)[0]), \
	ntohs(((uint16_t *)addr)[1]), \
	ntohs(((uint16_t *)addr)[2]), \
	ntohs(((uint16_t *)addr)[3]), \
	ntohs(((uint16_t *)addr)[4]), \
	ntohs(((uint16_t *)addr)[5]), \
	ntohs(((uint16_t *)addr)[6]), \
	ntohs(((uint16_t *)addr)[7])

#define NIP4_FMT_MAX_LEN (16)

#define NIP4_FMT "%d.%d.%d.%d"
#define NIP6_FMT "%X:%X:%X:%X:%X:%X:%X:%X"
#define NIP6_FMT_EX "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
#define NIP6_SEQFMT "%04x%04x%04x%04x%04x%04x%04x%04x"

#endif

#define HW_ADDR_FMT "%02hhx-%02hhx-%02hhx-%02hhx-%02hhx-%02hhx"
#define HW_ADDR_PTR(hw) \
	((unsigned char *)hw)[0], \
	((unsigned char *)hw)[1], \
	((unsigned char *)hw)[2], \
	((unsigned char *)hw)[3], \
	((unsigned char *)hw)[4], \
	((unsigned char *)hw)[5]


#define MKIPV4(a,b,c,d) \
    (uint32_t)(((uint8_t)d & 0xFF) << 24 | ((uint8_t)c & 0xFF) << 16 | ((uint8_t)b & 0xFF) << 8 | (a & 0xFF))

#define MKNL(a,b,c,d) \
    (uint32_t)(((uint8_t)d & 0xFF) << 24 | ((uint8_t)c & 0xFF) << 16 | ((uint8_t)b & 0xFF) << 8 | (a & 0xFF))

#define MKHL(a, b, c, d) \
    (uint32_t)(( ( a & 0xff) << 24 ) | ( ( b & 0xff) << 16 ) | ( ( c & 0xff) << 8 ) | ( ( d & 0xff) ) )


#define dbg( fmt, ...) printf( fmt, ##__VA_ARGS__ )

#define MAKEWORD(a, b)      ((WORD)(((BYTE)((DWORD_PTR)(a) & 0xff)) | ((WORD)((BYTE)((DWORD_PTR)(b) & 0xff))) << 8))
#define MAKELONG(a, b)      ((LONG)(((WORD)((DWORD_PTR)(a) & 0xffff)) | ((DWORD)((WORD)((DWORD_PTR)(b) & 0xffff))) << 16))
#define LOWORD(l)           ((WORD)((DWORD_PTR)(l) & 0xffff))
#define HIWORD(l)           ((WORD)((DWORD_PTR)(l) >> 16))
#define LOBYTE(w)           ((BYTE)((DWORD_PTR)(w) & 0xff))
#define HIBYTE(w)           ((BYTE)((DWORD_PTR)(w) >> 8))

#ifndef EXANGE_DWORD
	#define EXANGE_DWORD(dword) ((HIWORD(dword)) | (LOWORD(dword) << 16 ))
#endif

#ifndef EXANGE_WORD
	#define EXANGE_WORD(word)       ((HIBYTE(word)) | (LOBYTE(word) << 8))
#endif	

#if (RTE_MAX_LCORE > 32)
typedef uint64_t  cpu_mask_t;
#define zw_dp_cpu_mask_ffs __builtin_ffsl
#define zw_dp_cpu_mask(n) (1UL << n)
#else
typedef uint32_t  cpu_mask_t;
#define zw_dp_cpu_mask_ffs __builtin_ffs
#define zw_dp_cpu_mask(n) (1U << n)
#endif


#if (RTE_MAX_ETHPORTS > 16)
typedef uint32_t fwd_mda_t;
#else
typedef uint16_t fwd_mda_t;
#endif

typedef void    *MARKER[0];   /**< generic marker for a point in a structure */
typedef uint8_t  MARKER8[0];  /**< generic marker with 1B alignment */
typedef uint64_t MARKER64[0]; /**< marker that allows us to overwrite 8 bytes
                              * with a single assignment */


typedef uint16_t  MARKER16[0];  /**< generic marker with 2B alignment */
typedef uint32_t  MARKER32[0];  /**< generic marker with 4B alignment */
typedef __m128i   MARKER128[0];


typedef __uint128_t uint128_t;

#ifdef __tile__
typedef __uint128_t __m128i;
typedef uint64_t    __m64;
#endif
typedef union _zw_dp_xmm{	
	uint8_t _u8[16];	
	uint16_t _u16[8];	
	uint32_t _u32[4];	
	volatile uint64_t _u64[2];
	volatile __m64     m64[(sizeof(__uint128_t)) / sizeof(__m64)];
	double   pd[(sizeof(__uint128_t)) / sizeof(double)];
	volatile __uint128_t _u128;
	__m128i   m;
}
__attribute__((__aligned__(16)))
zw_dp_xmm_t;


//!
//! @brief 定义基本统计数据
//!
typedef union _pkt_stats{
	struct {
		uint64_t packets;	//!< 包数目
		uint64_t bytes;		//!< 字节数目
	};
	zw_dp_xmm_t xmm;
}
__attribute__((__aligned__(16)))
pkt_stats_t;

#ifdef __AVX2__
typedef union _ymm_pkt_stats{
	pkt_stats_t pkts[2];
	__m256i 	ymm;
}__attribute__((__aligned__(32)))
ymm_pkt_stats_t;
#endif

#define MKV2DI(a, b) ((__m128i){(uint64_t)(a), (uint64_t)(b)})



/**
 * @brief Flow解析结果
 *
 */
typedef struct zw_dp_xflow_stats {
	uint16_t sport;				/**< 源端口 */
	uint16_t dport;				/**< 目的端口 */	
	uint64_t pkts;				/**< 报文数量 */
	uint64_t Bytes;				/**< 字节数量 */
	union {
		struct // 与mirror 布局保持一致， 在geoip 统计中使用
		{
			uint32_t recv[3];
			uint32_t sip;			/**< IPv4源地址 */
		};		
		uint8_t  sip6[16];		/**< IPv6源地址 */
	};
	union {
		struct 
		{
			uint32_t recv2[3];
			uint32_t dip;			/**< IPv4目的地址 */
		};	
		
		uint8_t  dip6[16];		/**< IPv6目的地址 */
	};
	uint16_t sample_rate;		/**< sflow采样率/netflow的duration秒=(Last-First)/1000 */
	uint16_t ethtype;			/**< 以太类型 */
	uint8_t  prot;				/**< 协议类型 */
	uint8_t  tcp_flags;
}zw_dp_xflow_stats_t;

#define MAX_XFLOW_STATS_NUM_PER_PKT  512

#ifdef __cplusplus
}
#endif

#endif
